```python
"""Collection classes for managing multiple tools."""
from typing import Any, Dict, List

from app.exceptions import ToolError
from app.tool.base import BaseTool, ToolFailure, ToolResult


class ToolCollection:
    """
    ToolCollection类用于管理多个工具的集合。

    该类提供了对工具的添加、执行、获取等操作。
    """

    class Config:
        """
        允许任意类型的配置。
        """
        arbitrary_types_allowed = True

    def __init__(self, *tools: BaseTool):
        """
        初始化ToolCollection对象。

        Args:
            *tools (BaseTool): 一个或多个BaseTool对象，表示要管理的工具。
        """
        self.tools = tools
        self.tool_map = {tool.name: tool for tool in tools}

    def __iter__(self):
        """
        使ToolCollection对象可迭代。

        Returns:
            iter: 返回一个迭代器，包含所有工具对象。
        """
        return iter(self.tools)

    def to_params(self) -> List[Dict[str, Any]]:
        """
        将所有工具转换为参数列表。

        Returns:
            List[Dict[str, Any]]: 返回一个包含所有工具参数的列表。
        """
        return [tool.to_param() for tool in self.tools]

    async def execute(
        self, *, name: str, tool_input: Dict[str, Any] = None
    ) -> ToolResult:
        """
        根据工具名执行对应的工具。

        Args:
            name (str): 要执行的工具名。
            tool_input (Dict[str, Any], optional): 工具执行时所需的输入参数。默认为None。

        Returns:
            ToolResult: 返回工具执行的结果。如果工具不存在或执行失败，返回ToolFailure对象。
        """
        tool = self.tool_map.get(name)
        if not tool:
            return ToolFailure(error=f"Tool {name} is invalid")
        try:
            result = await tool(**tool_input)
            return result
        except ToolError as e:
            return ToolFailure(error=e.message)

    async def execute_all(self) -> List[ToolResult]:
        """
        顺序执行集合中的所有工具。

        Returns:
            List[ToolResult]: 返回一个包含所有工具执行结果的列表。如果某个工具执行失败，结果中会包含ToolFailure对象。
        """
        results = []
        for tool in self.tools:
            try:
                result = await tool()
                results.append(result)
            except ToolError as e:
                results.append(ToolFailure(error=e.message))
        return results

    def get_tool(self, name: str) -> BaseTool:
        """
        根据工具名获取对应的工具对象。

        Args:
            name (str): 要获取的工具名。

        Returns:
            BaseTool: 返回对应的工具对象，如果工具不存在则返回None。
        """
        return self.tool_map.get(name)

    def add_tool(self, tool: BaseTool):
        """
        向集合中添加一个工具。

        Args:
            tool (BaseTool): 要添加的工具对象。

        Returns:
            ToolCollection: 返回当前的ToolCollection对象，以支持链式调用。
        """
        self.tools += (tool,)
        self.tool_map[tool.name] = tool
        return self

    def add_tools(self, *tools: BaseTool):
        """
        向集合中添加多个工具。

        Args:
            *tools (BaseTool): 一个或多个要添加的工具对象。

        Returns:
            ToolCollection: 返回当前的ToolCollection对象，以支持链式调用。
        """
        for tool in tools:
            self.add_tool(tool)
        return self
```